<script setup lang="ts">
/**
 * @description 一个通用的图片网格组件，根据传入的 width 和 cols 计算出图片尺寸。
 * mode 为 edit 时，网格尾部显示一个按钮，点击可以从相机或相册中选择照片。
 */
const props = defineProps<{
  mode: 'edit' | 'display'
  width: number
  cols: number
  medium: string[]
  videoCovers: string[]
}>()

const emit = defineEmits(['pickImage', 'delete'])

const pictureSize = computed(() => (props.width - 25 * (props.cols - 1)) / props.cols)

export interface Media { type: 'image' | 'video', index: number, url: string, coverUrl?: string }

const mediumList = computed(() => {
  const displayedMedium: Media[] = []

  let videoCount = 0

  props.medium.forEach((media) => {
    if (media.includes('.mp4')) {
      displayedMedium.push({
        type: 'video',
        index: displayedMedium.length,
        url: media,
        coverUrl: props.videoCovers[videoCount],
      })
      videoCount += 1
    }
    else if (media.includes('.png') || media.includes('.jpg')) {
      displayedMedium.push({
        type: 'image',
        index: displayedMedium.length,
        url: media,
      })
    }
  })

  return displayedMedium
})

const currentVideo = ref('')
const isShowVideoPlayer = ref(false)

function handlePreview(index: number, medium: Media[]) {
  if (medium[index].type === 'image') {
    uni.previewImage({
      current: index,
      showmenu: true,
      urls: medium.map(media => media.type === 'image' ? media.url : media.coverUrl) as string [],
      indicator: 'number',
    })
  }
  else {
    currentVideo.value = medium[index].url
    isShowVideoPlayer.value = true
  }
}

function handleDelete(media: Media) {
  uni.showModal({
    title: '提示',
    content: media.type === 'image' ? '确定要删除这张图片吗？' : '确定要删除这条视频吗？',
    success: (result) => {
      if (result.confirm)
        emit('delete', media)
    },
  })
}
</script>

<template>
  <view class="grid gap-25rpx" :style="{ gridTemplateColumns: `repeat(${props.cols}, minmax(0, 1fr))` }">
    <view
      v-for="media, index in mediumList"
      :key="index"
      class="relative"
      :style="{ width: `${pictureSize}rpx`, height: `${pictureSize}rpx` }"
    >
      <!-- 图片 Item -->
      <div class="relative">
        <image
          class="rounded-20rpx"
          :style="{ width: `${pictureSize}rpx`, height: `${pictureSize}rpx` }"
          mode="aspectFill"
          :src="media.type === 'image' ? media.url : media.coverUrl"
          @tap="handlePreview(index, mediumList)"
        />
        <image
          v-if="media.type === 'video'"
          class="absolute left-1/2 top-1/2 h-30rpx w-27rpx -translate-1/2"
          src="@/static/images/play.png"
        />
      </div>
      <!-- 右上角删除按钮 -->
      <view
        v-if="props.mode === 'edit'"
        class="absolute h-40rpx w-40rpx flex items-center justify-center rounded-32rpx bg-#D3D3D3 -right-20rpx -top-20rpx"
        @tap="() => handleDelete(media)"
      >
        <uv-icon name="close" size="20rpx" color="#ffffff" />
      </view>
    </view>
    <!-- 上传照片按钮 -->
    <button
      v-if="mode === 'edit'"
      class="m-0 flex flex-col items-center justify-center border-1px border-#D3D3D3 rounded-10rpx border-solid bg-white p-0"
      hover-class="tapped"
      :style="{ width: `${pictureSize}rpx`, height: `${pictureSize}rpx` }"
      @tap="$emit('pickImage')"
    >
      <image class="h-33rpx w-36rpx" src="@/static/images/camera.png" />
      <Spacer height="20" />
      <view class="text-tertiary text-28rpx leading-28rpx">
        上传文件
      </view>
    </button>
  </view>

  <div v-if="isShowVideoPlayer" class="fixed left-0 top-0 z-[100] h-screen w-screen bg-black bg-opacity-40" @tap="isShowVideoPlayer = false">
    <video class="absolute left-1/2 top-1/2 aspect-video -translate-1/2" :src="currentVideo" @tap.stop />
  </div>
</template>

<style scoped>
.tapped {
  background-color: #F8F8F8;
}
</style>
